#include <stdio.h>
#include <string.h>
#include <gmssl/sm2.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
#include <gmssl/sm3.h> 
#include <stdint.h>

// SM3 摘要长度
#define SM3_HASH_SIZE 32

// (复用 print_hex 函数)
void print_hex(const char* label, const unsigned char* data, int len) {
    printf("%s (%d bytes):\n", label, len);
    for (int i = 0; i < len; ++i) {
        printf("%02x", data[i]);
    }
    printf("\n");
}

int main() {
    SM2_KEY key;
    const uint8_t *msg = (const uint8_t *)"Test message for GmSSL SM2";
    size_t msg_len = strlen((char*)msg);
    
    uint8_t ciphertext[1024];
    size_t ciphertext_len = 0;
    uint8_t decryptedtext[1024];
    size_t decryptedtext_len = 0;

    printf("----------------------------------------\n");
    printf("1. SM2 Key Generation\n");
    printf("----------------------------------------\n");
    
    // 1. 生成 SM2 密钥
    if (sm2_key_generate(&key) != 1) {
        fprintf(stderr, "sm2_key_generate failed\n");
        return 1;
    }
    printf("SM2 Key generation successful.\n");

    printf("\n----------------------------------------\n");
    printf("2. SM2 Encryption and Decryption\n");
    printf("----------------------------------------\n");

    // 2. SM2 加密 (C1C3C2 格式)
    if (sm2_encrypt(&key, msg, msg_len, ciphertext, &ciphertext_len) != 1) {
        fprintf(stderr, "sm2_encrypt failed\n");
        return 1;
    }
    print_hex("SM2 Ciphertext (C1C3C2)", ciphertext, (int)ciphertext_len);

    // 3. SM2 解密
    if (sm2_decrypt(&key, ciphertext, ciphertext_len, decryptedtext, &decryptedtext_len) != 1) {
        fprintf(stderr, "sm2_decrypt failed\n");
        return 1;
    }

    if (decryptedtext_len < 1024) {
        decryptedtext[decryptedtext_len] = '\0';
    }

    printf("SM2 Decrypted length: %zu bytes\n", decryptedtext_len);
    printf("SM2 Decrypted text: %s\n", decryptedtext);
    
    if (decryptedtext_len == msg_len && memcmp(msg, decryptedtext, msg_len) == 0) {
        printf("SM2 Enc/Dec Success!\n");
    } else {
        printf("SM2 Enc/Dec Failed!\n");
    }

    // ---------------------------------
    printf("\n----------------------------------------\n");
    printf("3. SM2 Signing and Verification (Using Raw Signature)\n");
    printf("----------------------------------------\n");

    // 签名和验签所需：H(Z || M)
    uint8_t z[SM3_HASH_SIZE];
    uint8_t hash[SM3_HASH_SIZE];
    const char *id = "1234567812345678";
    
    // 准备用于存放签名结果的原始字节数组（DER格式）
    uint8_t sig_der[SM2_MAX_SIGNATURE_SIZE];
    size_t sig_len = 0; 
    
    // 计算 Z 值 (公钥哈希)
    if (sm2_compute_z(z, &key.public_key, id, strlen(id)) != 1) {
         fprintf(stderr, "sm2_compute_z failed\n");
         return 1;
    }
    
    // 计算 H(Z || M) 
    SM3_CTX sm3_ctx; 
    sm3_init(&sm3_ctx);
    sm3_update(&sm3_ctx, z, sizeof(z));
    sm3_update(&sm3_ctx, msg, msg_len);
    sm3_finish(&sm3_ctx, hash); // 使用 sm3_finish

    print_hex("SM3(Z||M) for signing", hash, sizeof(hash));

    // 执行签名：sm2_sign将结果直接写入 sig_der 数组
    if (sm2_sign(&key, hash, sig_der, &sig_len) != 1) { // 修正参数列表
         fprintf(stderr, "sm2_sign failed\n");
         return 1;
    }

    print_hex("SM2 Signature (DER)", sig_der, (int)sig_len);

    // 4. SM2 验签
    // sm2_verify 需要 SM2_KEY 结构体，以及原始签名数据和长度
    // 验签使用私钥/公钥对中的公钥部分
    if (sm2_verify(&key, hash, sig_der, sig_len) == 1) { // 修正参数列表
        printf("SM2 Signature Verification Success!\n");
    } else {
        printf("SM2 Signature Verification Failed!\n");
    }

    // 注意：sm2_signature_to_der 和 sm2_signature_from_der
    // 在你的GMSSL版本中API较为复杂，且在本例中不再需要，故移除。

    return 0;
}

